/*
 * 文件名： WcPayCmbcServiceImpl.java
 * 
 * 工程名称: bis-bank-wechat
 *
 * Gopay
 *
 * 创建日期： 2017年5月16日
 *
 * Copyright(C) 2017, by www.gopay.com.cn Inc.All rights reserved.
 *
 * 原始作者: 宣广海
 *
 */
package com.gopay.bis.cmbc.wcpay.impl;

import com.gopay.bis.cmbc.wcpay.operation.CryptoUtil;
import com.gopay.bis.cmbc.wcpay.operation.WcPayCmbcHelper;
import com.gopay.bis.common.trace.PaymentLog;
import com.gopay.common.constants.bank.BankLogConstants;
import com.gopay.common.constants.bank.CmbcConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.BisBankReturnVo;
import com.gopay.common.domain.bank.wechat.wcpay.cmbc.*;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.HttpsTransport;
import com.gopay.remote.bank.businesses.WcPayService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信公众号/支付宝服务窗支付民生银行渠道报文交互业务处理
 *
 * @author 宣广海
 *
 * @version 
 *
 * @since 2017年5月16日
 */
public class WcPayCmbcServiceImpl implements WcPayService{
	
	private static Logger logger = LoggerFactory.getLogger(WcPayCmbcServiceImpl.class);
	
	private WcPayCmbcHelper wcPayCmbcHelper;
	private HttpsTransport httpTransportImpl;

	private String kafkaSwitch;

	@Override
	public Object verify(BaseMessage baseMsg) throws GopayException {
		return wcPayCmbcHelper.verify(baseMsg);
	}

	@Override
	public Object payment(BaseMessage baseMsg) throws GopayException {	 	
			Object res = null;
			String reqMsgId = baseMsg.getBankOrderId();// 支付订单需要上送的银行订单号
			logger.info("cmbc wcpay request MsgId :" + baseMsg.getBankOrderId());
			TransMsg<PayMsgBody> resMessage = null;
			Map<String, String> params = new HashMap<String, String>();
			try {
				Map<String, String> param = generateParam(baseMsg, CmbcConstants.JS_PAY, reqMsgId);
				httpTransportImpl.setUrl(baseMsg.getPayUrl());
				res = httpTransportImpl.submit(param);
				/**
				 * 解密并验签
				 */
				String plainText = wcPayCmbcHelper.buildResponseData(res.toString(), baseMsg);
				if (null != plainText) {
					/**
					 * 解析xml报文
					 */
					params = wcPayCmbcHelper.generateResMsgtoMap(plainText);
					resMessage=generateResPayMessage(params);

					//发送银行返回的所有请求 插入到kafka中，
					BisBankReturnVo vo = new BisBankReturnVo();
					//国付宝订单号
					vo.setGopayOrderId(baseMsg.getOrderId());
					//银行返回订单号
					vo.setBankOrderId(resMessage.getMsgBody().getChannelNo());
					//银行渠道
					vo.setBankChannel(baseMsg.getBankIntrChann().value);
					//银行编码 比如 ICBC  ABC
					vo.setBankCode(BankLogConstants.BANK_LOG_WC_PAY_CMBC);
					//银行返回错误的xml文件信息
					vo.setBankReturnXml(plainText.toString());
					//银行返回错误码
					vo.setRsCode(resMessage.getMsgHead().getRespCode());
					//银行返回的错误信息
					vo.setRsMsg(resMessage.getMsgHead().getRespMsg());
					//银行报文订单返回时间
					vo.setBankReturnDate(resMessage.getMsgHead().getRespDate());
					//报文返回记录日志时间  时间格式：yyyy-MM-dd HH:mm:ss
					vo.setCreateTsErr(DateUtils.getCurrDate("yyyy-MM-dd HH:mm:ss"));
					//保存到kafka中
					PaymentLog.info(vo,kafkaSwitch);
				} else {
					throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
				}
				return resMessage;
			} catch (Exception e) {
				logger.error("send occur error ", e.getMessage());
				throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
			}
		
	}

	@Override
	public Object refund(BaseMessage baseMsg) throws GopayException {
		Object res = null;
		String reqMsgId = baseMsg.getBankOrderId();// 退款订单需要上送的银行订单号
		logger.info("cmbc wcpay refund request MsgId :" + reqMsgId);
		TransMsg<RefundMsgBody> resMessage = null;
		Map<String, String> params = new HashMap<String, String>();
		try {
			Map<String, String> param = generateParam(baseMsg, CmbcConstants.REFUND, reqMsgId);
			httpTransportImpl.setUrl(baseMsg.getPayUrl());
			res = httpTransportImpl.submit(param);
			/**
			 * 解密并验签
			 */
			String plainText = wcPayCmbcHelper.buildResponseData(res.toString(), baseMsg);
			if (null != plainText) {
				/**
				 * 解析xml报文
				 */
				params = wcPayCmbcHelper.generateResMsgtoMap(plainText);
				resMessage=generateResRefundMessage(params);
			} else {
				throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
			}
			return resMessage;
		} catch (Exception e) {
			logger.error("send occur error ", e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E1160);
		}
	
	}

	@Override
	public Object queryOrder(BaseMessage baseMsg) throws GopayException {
		Object res = null;
		String reqMsgId = baseMsg.getOrderId();// 查询订单需要上送订单号，保证当前请求号唯一。
		logger.info("cmbc wcpay query request MsgId :" + reqMsgId);
		TransMsg<QueryMsgBody> resMessage = null;
		Map<String, String> params = new HashMap<String, String>();
		try {
			Map<String, String> param = generateParam(baseMsg, CmbcConstants.ORDER_QUERY, reqMsgId);
			httpTransportImpl.setUrl(baseMsg.getQueryUrl());
			res = httpTransportImpl.submit(param);
			/**
			 * 解密并验签
			 */
			String plainText = wcPayCmbcHelper.buildResponseData(res.toString(), baseMsg);
			if (null != plainText) {
				/**
				 * 解析xml报文
				 */
				params = wcPayCmbcHelper.generateResMsgtoMap(plainText);
				resMessage=generateResQueryMessage(params);
			} else {
				throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
			}
			return resMessage;
		} catch (Exception e) {
			logger.error("send occur error ", e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7027);
		}
	}

	@Override
	public Object refundQuery(BaseMessage baseMsg) throws GopayException {
		// TODO Auto-generated method stub
		return null;
	}
	/**
	 * 
	 * 功能描述：构建提交民生银行参数
	 *
	 * @param baseMsg
	 * @param tranCode
	 * @param reqMsgId
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年5月16日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Map<String, String> generateParam(BaseMessage baseMsg, String tranCode,String reqMsgId) throws GopayException {
		Map<String, String> param = new HashMap<String, String>();
		byte[] keyBytes = null;
		try {
			String signData = wcPayCmbcHelper.sign(baseMsg);
			keyBytes = CryptoUtil.generateRandomKey(16).getBytes("utf-8");
			String encrtptKey = wcPayCmbcHelper.encrtptKey(keyBytes, baseMsg);
			String encryptData = wcPayCmbcHelper.encryptData(baseMsg, keyBytes);
			param.put("encryptData", encryptData);
			param.put("encryptKey", encrtptKey);
			param.put("signData", signData);
			param.put("callBack", baseMsg.getPayRuturnUrl());
			param.put("reqMsgId", reqMsgId);
			/**
			 * 支付宝和微信的渠道号不一样
			 */
			param.put("cooperator", baseMsg.getMerID());
			param.put("tranCode", tranCode);
			param.put("ext", "");
			logger.info("cmbc scan submit param :");
		} catch (Exception e) {
			logger.error("wechat wcpay is error,"+e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7025,e);
		}
		return param;
	}
	public TransMsg<PayMsgBody> generateResPayMessage(Map<String, String> params) throws Exception {
		MsgHead head = new MsgHead();
		PayMsgBody body = new PayMsgBody();
		TransMsg<PayMsgBody> resMessage = new TransMsg<PayMsgBody> ();
		generateResHeadMessage(head,params);

		body.setWxjsapiStr(params.get("wxjsapiStr"));
		body.setChannelNo(params.get("channelNo"));
		body.setPrepayId(params.get("prepayId"));
		body.setExtend1(params.get("extend1"));
		body.setExtend2(params.get("extend2"));
		body.setExtend3(params.get("extend3"));
		resMessage.setMsgHead(head);
		resMessage.setMsgBody(body);
		return resMessage;
	}	
	public TransMsg<RefundMsgBody> generateResRefundMessage(Map<String, String> params) throws Exception {
		MsgHead head = new MsgHead();
		RefundMsgBody body = new RefundMsgBody();
		TransMsg<RefundMsgBody> resMessage = new TransMsg<RefundMsgBody> ();
		generateResHeadMessage(head,params);
		BigDecimal refundAmunt=StringUtils.isNotBlank(params.get("refundAmount"))?new BigDecimal(params.get("refundAmount")):new BigDecimal(0);
		BigDecimal refundFee=StringUtils.isNotBlank(params.get("refundFee"))?new BigDecimal(params.get("refundFee")):new BigDecimal(0);
		BigDecimal backFee=StringUtils.isNotBlank(params.get("backFee"))?new BigDecimal(params.get("backFee")):new BigDecimal(0);
		body.setRefundAmount(refundAmunt);
		body.setRefundFee(refundFee);
		body.setBackFee(backFee);
		body.setOriReqMsgId(params.get("oriReqMsgId"));
		body.setExtend1(params.get("extend1"));
		body.setExtend2(params.get("extend2"));
		body.setExtend3(params.get("extend3"));
		resMessage.setMsgHead(head);
		resMessage.setMsgBody(body);
		return resMessage;
	}
	public TransMsg<QueryMsgBody> generateResQueryMessage(Map<String, String> params) throws Exception {
		MsgHead head = new MsgHead();
		QueryMsgBody body = new QueryMsgBody();
		TransMsg<QueryMsgBody> resMessage = new TransMsg<QueryMsgBody> ();
		generateResHeadMessage(head,params);
		
		body.setOriReqMsgId(params.get("oriReqMsgId"));
		body.setOriRespType(params.get("oriRespType"));
		body.setOriRespCode(params.get("oriRespCode"));
		body.setOriRespMsg(params.get("oriRespMsg"));
		body.setTotalAmount(StringUtils.isNotBlank(params.get("totalAmount"))?new BigDecimal(params.get("totalAmount")):new BigDecimal(0));
		body.setBuyerPayAmount(StringUtils.isNotBlank(params.get("buyerPayAmount"))?new BigDecimal(params.get("buyerPayAmount")):new BigDecimal(0));
		body.setPointAmount(StringUtils.isNotBlank(params.get("pointAmount"))?new BigDecimal(params.get("pointAmount")):new BigDecimal(0));
		body.setIsClearOrCancel(params.get("isClearOrCancel"));
		body.setExtend1(params.get("extend1"));
		body.setExtend2(params.get("extend2"));
		body.setExtend3(params.get("extend3"));
		resMessage.setMsgHead(head);
		resMessage.setMsgBody(body);
		return resMessage;
	}	
	public MsgHead generateResHeadMessage(MsgHead head,Map<String, String> params) throws Exception {
		head.setVersion(params.get("version"));
		head.setMsgType(params.get("msgType"));
		head.setReqDate(params.get("reqDate"));
		head.setRespCode(params.get("respCode"));
		head.setRespDate(params.get("respDate"));
		head.setRespMsg(params.get("respMsg"));
		head.setRespType(params.get("respType"));
		head.setSmzfMsgId(params.get("smzfMsgId"));
		return head;
	}
	
	
	public WcPayCmbcHelper getWcPayCmbcHelper() {
		return wcPayCmbcHelper;
	}

	public void setWcPayCmbcHelper(WcPayCmbcHelper wcPayCmbcHelper) {
		this.wcPayCmbcHelper = wcPayCmbcHelper;
	}

	public HttpsTransport getHttpTransportImpl() {
		return httpTransportImpl;
	}

	public void setHttpTransportImpl(HttpsTransport httpTransportImpl) {
		this.httpTransportImpl = httpTransportImpl;
	}

	public String getKafkaSwitch() {
		return kafkaSwitch;
	}

	public void setKafkaSwitch(String kafkaSwitch) {
		this.kafkaSwitch = kafkaSwitch;
	}
}
